//
//  MoneyState.m
//  iMoney
//
//  Created by VertigoSol on 9/12/08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "MoneyState.h"

#define dbName		@"imoney.sql"


@implementation MoneyState


//Copies the database from the resources bundle if not found on the
//user's iPhone.
-(BOOL)copyDatabase {
	
	BOOL success;
	NSError *error;
	
	//FileManager - Object allows easy access to the File System.
	NSFileManager *FileManager = [NSFileManager defaultManager];
	
	//Get the complete users document directory path.
	NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
	
	//Get the first path in the array.
	NSString *documentsDirectory = [paths objectAtIndex:0];
	
	//Create the complete path to the database file.
	NSString *databasePath = [documentsDirectory stringByAppendingPathComponent:dbName];
	
	//Check if the file exists or not.
	success = [FileManager fileExistsAtPath:databasePath];
	
	//If the database is present then quit.
	if(success) return YES;
	
	//the database does not exists, so we will copy it to the users document directory]
	NSString *dbPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbName];
	
	//Copy the database file to the users document directory.
	success = [FileManager copyItemAtPath:dbPath toPath:databasePath error:&error];
	
	//If the above operation is not a success then display a message.
	//Error message can be seen in the debugger's console window.
	if(!success){
		NSLog(@"Failed to copy the database. Error: %@.", [error localizedDescription]);
	}
	
	return success;
	
}

-(id) init
{
	if(self = [super init])
	{
		accounts = [[NSMutableArray alloc] init]; 
		//[self copyDatabase];
	}
	
	
	return self;
}


-(void) clearAllAccounts
{
	[accounts removeAllObjects];
}


//get a single account by index
-(Account*) getAccount:(NSUInteger) index
{
	return [accounts objectAtIndex:index];
}

-(void) addAccount: (Account*) acc
{
	[accounts addObject:acc];
}

-(void) removeAccount: (Account*) acc
{
	[accounts removeObject:acc];
}


-(void) removeAccountIndex: (NSInteger) index
{
	[accounts removeObjectAtIndex:index];
}


 //Test to see if two account names are equal
-(BOOL) containsAccount: (NSString*) name
{
	BOOL does = NO;
	for(Account* a in accounts)
	{
		if([a.accountName caseInsensitiveCompare:name] == 0)
		{
			does = YES;
		}
		
	}
	
	return does;
	
}

//account count
-(int) numAccounts
{
	return [accounts count];
}




-(double) getTotalAccountsAmount
{
	double amount=0;
	
	for(Account* a in accounts)
	{
		amount+= (a.totalAmount + a.offsetAmount);
	}
	
	return amount;
	
}

-(NSMutableDictionary*) getExpenseList
{
	NSMutableDictionary* dict = [[[NSMutableDictionary alloc] init] autorelease];
		
	
	for( Account* a in accounts)
	{
		for(Expense* e in [a expenses])
		{
			[dict setValue:@"1" forKey:[e ename]];
		}
		
		
	}
	
	return dict;
	
}


-(NSArray*) getTypeList
{
	
		
	if(expenseTypeList != nil)
	{
		[expenseTypeList release];
	}
		
	
	NSMutableDictionary* dict = [NSMutableDictionary new];
	
	
	for( Account* a in accounts)
	{
		for(Expense* e in [a expenses])
		{
			[dict setValue:@"1" forKey:[e type]];
		}
		
		
	}
		
	expenseTypeList = [NSArray arrayWithArray:[dict allKeys]];	
	
	[dict release];
		
	
	return expenseTypeList;
	
}


//--------------------------

-(BOOL) parseXmlFromFile:(NSString*)filePath
{
	
	[self clearAllAccounts];
	
	NSURL *xmlURL = [NSURL fileURLWithPath:filePath];
	NSXMLParser* parser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
	if(parser == nil)
	{
		NSLog(@"Error crearing parser");
		return NO;
	}
	
	[parser setDelegate:self];
	[parser setShouldProcessNamespaces:NO]; // We don't care about namespaces
    [parser setShouldReportNamespacePrefixes:NO]; //
    [parser setShouldResolveExternalEntities:NO]; // We just want data, no other stuff
	
	BOOL couldParse = [parser parse];

	if(!couldParse)
	NSLog(@"Couldnt Parse");
	
	//[xmlURL release];
	[parser release];
	
	return couldParse;
}

-(BOOL) parseXmlFromData:(NSData*)xmlData
{
	
	[self clearAllAccounts];
	
	NSXMLParser* parser = [[NSXMLParser alloc] initWithData:xmlData];
	if(parser == nil)
	{
		NSLog(@"Error crearing parser");
		return NO;
	}
	
	[parser setDelegate:self];
	[parser setShouldProcessNamespaces:NO]; // We don't care about namespaces
    [parser setShouldReportNamespacePrefixes:NO]; //
    [parser setShouldResolveExternalEntities:NO]; // We just want data, no other stuff
	
	BOOL couldParse = [parser parse];
	
	if(!couldParse)
		NSLog(@"Couldnt Parse");
	
	//[parser release];
	
	return couldParse;
}


-(NSString*) removeNewline:(NSString*) string
{
	int i=0;
	
	for(i=0; i < [string length]; i++)
	{
		if([string characterAtIndex:i] != '\n' && [string characterAtIndex:i] != ' ' )
		{
			break;
		}
		
	}
	
	NSString* noNew = [string stringByReplacingOccurrencesOfString:@"\n" 
														withString:@"" options:0 range:NSMakeRange(0, [string length] -i)];
	
	return [noNew stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}


- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
	if([elementName isEqualToString:@"Account"])
	{
		attrib = [attributeDict objectForKey:@"name"];
		if(attrib != nil)
		{
			tempAccount = [[Account alloc] initWithName:attrib];
			tempAccount.accountName = [attrib copy];
		}
	}
	else if([elementName isEqualToString:@"Expense"])
	{
		if(tempAccount != nil)
		{
			NSString* name = [attributeDict objectForKey:@"name"];
			NSString* type = [attributeDict objectForKey:@"type"];
			NSString* amount = [attributeDict objectForKey:@"amount"];
			NSString* dates = [attributeDict objectForKey:@"date"];

			NSDate* date = [NSDate dateWithTimeIntervalSince1970:[dates floatValue]];
			
			tempExpense = [[Expense alloc] initAll:date :name :type :[amount floatValue]];
			[tempAccount addExpense:tempExpense:YES];
		}
		
	}
	

}


- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
	if([elementName isEqualToString:@"Account"])
	{
		if(tempAccount != nil)
		{
			[self addAccount:tempAccount]; //add account to pool
			[tempAccount release];
			tempAccount = nil;
		}
			
	}
	else if([elementName isEqualToString:@"Expense"])
	{
		tempExpense.note = [self removeNewline:tempData];
		[tempExpense release];
	}
	
	
	[tempData release];
	tempData = nil;
	
}


- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
	if(!tempData)
	{
		tempData = [[NSMutableString alloc] init];
	}
	
	
	if([string length] > 0)
	//keep adding data <> data </> 
		[tempData appendString:[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
}

//------------------


-(NSMutableString*) getDataXML: (BOOL) millisecTime
{
	
	NSMutableString* outStr = [[[NSMutableString alloc] init] autorelease];
	
	
	//add header
	[outStr	appendString:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"];
	
	NSString* dataHead = [NSString stringWithFormat:@"<Data date=\"%f\">", [[NSDate date] timeIntervalSince1970]];
	[outStr	appendString:dataHead];
	
	for(int i=0; i < [accounts count]; i++)
	{
		
		[outStr appendFormat:@"<Account name=\"%@\">", [[self getAccount:i] accountName]];
		
		
		for(int j=0; j < [[self getAccount:i] count]; j++)
		{
			Expense* e = [[self getAccount:i] getExpense: j];
			
			double time = [[e date] timeIntervalSince1970]; //time expressed in secs
			if(millisecTime)
				time *=1000;
			
			[outStr appendFormat:@"<Expense name=\"%@\" type=\"%@\" amount=\"%f\" date=\"%f\">",
			 [e ename], [e type], [e amount], time];
			
			if([[e note] length] > 2)
			[outStr appendFormat:@"%@", [e note]];
			
			[outStr appendString:@"</Expense>"];
		}
		
		
		[outStr appendFormat:@"</Account>"];
	}
	
	[outStr	appendString:@"</Data>"];	
	return outStr;
}


-(BOOL) saveDataFile:(NSString*) path
{
	BOOL didSave =NO;
	
	NSError* error;
	[[self getDataXML:NO] writeToFile:path atomically:YES encoding:NSUnicodeStringEncoding error:&error];
	
	if(error !=nil)
		didSave = YES;
	
	
	return didSave;
	
}

-(void) dealloc
{
	[expenseTypeList release];
	[tempData release];
	[tempAccount release];
	[tempExpense release];
	[accounts release];
	[super dealloc];
}


@end
